package com.translate.commons.asynctask;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/********************************************
 * 异步任务执行顺.<br>
 * 用于执行时间较长，需要异步执行的任务<br>
 * 该类需要通过SRPING实例化，具体调用的时候通过静态方法调用<br>
 *********************************************/
public class AsyncTaskExecutor implements Runnable {
    /* 处理线程 */
    private Thread thExcute;
    /* 待处理队列 */
    private BlockingQueue<KeyValuePair<String, AsyncTaskBase>> pendingQueue;
    /* 待处理任务ID列表 */
    private List<String> pendingIds;
    /* 已完成任务清单 */
    private Map<String, AsyncTaskBase> complateList;
    /* 当前正在执行的任务 */
    private Map<String, AsyncTaskBase> currentList;
    /* 最大队列数 */
    private int maxQueueSize = 400;
    /* 执行线程是否正在执行 */
    private static boolean isRunning = false;
    /*线程默认自动销毁时间*/
    private int destroyTime=5*60*1000;

    public AsyncTaskExecutor() {
        pendingQueue = new ArrayBlockingQueue<KeyValuePair<String, AsyncTaskBase>>(maxQueueSize);
        pendingIds = new ArrayList<>();
        complateList = new HashMap<String, AsyncTaskBase>();
        currentList = new HashMap<String, AsyncTaskBase>();
    }

    /********************************************
     * 执行线程主体方法.<br>
     * @since v1.0.0
     * 参数名 参数类型 参数描述
     * @return 返回类型 返回类型描述
     * <br>
     *********************************************/
    @Override
    public void run() {
        while (true) {
            try {
                // 通过take方法提取一个任务，当队列为空时挂住线程
                KeyValuePair<String, AsyncTaskBase> currentTask = pendingQueue.take();
                String taskId = (String) currentTask.getKey();
                AsyncTaskBase taskObject = (AsyncTaskBase) currentTask.getValue();
                taskObject.setTaskId(taskId);
                currentList.put(taskId, taskObject);
                pendingIds.remove(taskId);
                Thread tr = new Thread(taskObject);
                tr.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    /********************************************
     * 开始执行任务.<br>
     * 方法业务逻辑详细描述……<br>
     * @since v1.0.0
     * 参数名 参数类型 参数描述
     * @return 返回类型 返回类型描述
     * <br>
     *********************************************/
    public void start() {
        if (isRunning) {
            return;
        }
        thExcute = new Thread(this);
        thExcute.start();
        isRunning = true;
    }

    /********************************************
     * 停止执行任务.<br>
     * 方法业务逻辑详细描述……<br>
     * @since v1.0.0
     * 参数名 参数类型 参数描述
     * @return 返回类型 返回类型描述
     * <br>
     *********************************************/
    public void stop() {
        thExcute.interrupt();
        isRunning = false;
    }

    /********************************************
     * 暂停任务执行.<br>
     * 方法业务逻辑详细描述……<br>
     * @since v1.0.0
     * 参数名 参数类型 参数描述
     * @return 返回类型 返回类型描述
     * <br>
     *********************************************/
    public void pause() {
        try {
            thExcute.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /********************************************
     * 恢复任务执行.<br>
     * 方法业务逻辑详细描述……<br>
     * @since v1.0.0
     * 参数名 参数类型 参数描述
     * @return 返回类型 返回类型描述
     * <br>
     *********************************************/
    public void resume() {
        thExcute.notify();
    }

    public String push(AsyncTaskBase task) {
        task.setTaskExecutor(this);
        try {
            // 如果还没有显式地启动过则启动一下
            if (!isRunning) {
                start();
            }
            String id = UUID.randomUUID().toString();
            KeyValuePair<String, AsyncTaskBase> kvp = new KeyValuePair<String, AsyncTaskBase>();
            kvp.setKey(id);
            kvp.setValue(task);
            pendingQueue.put(kvp);
            pendingIds.add(id);
            return id;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        }
    }

    /********************************************
     * 获取一个已经执行完的任务实例.<br>
     * 通过任务ID获取一个已经执行完的任务 <br>
     * @since v1.0.0
     * @param id String 任务ID
     * @return IAsyncTask 任务实例，具体里面的取值由应用层自行处理
     * <br>
     *********************************************/
    public AsyncTaskBase pull(String id) {
        if (complateList.containsKey(id)) {
            AsyncTaskBase task = complateList.remove(id);
            return task;
        }
        return null;
    }

    /********************************************
     * 检测一个任务的执行状态.<br>
     * 通过任务ID获取任务的执行状态 <br>
     * @since v1.0.0
     * @param id String 任务ID
     * @return AsyncTaskStatus 任务执行状态，其中包括状态和执行进度
     * <br>
     *********************************************/
    public AsyncTaskStatus checkStatus(String id) {
        // 任务正在执行
        if (currentList.containsKey(id)) {
            AsyncTaskStatus status = new AsyncTaskStatus();
            status.setStatus(AsyncTaskStatus.STTAUS_RUNNING);
            AsyncTaskBase task = (AsyncTaskBase) currentList.get(id);
            status.setProgress(task.getProgress());
            return status;
        }
        // 任务已经完成
        if (complateList.containsKey(id)) {
            AsyncTaskStatus status = new AsyncTaskStatus();
            status.setStatus(AsyncTaskStatus.STATUS_COMPLATE);
            status.setProgress(100);
            return status;
        }
        // 任务还在计划中，未进行执行阶段
        if (pendingIds.contains(id)) {
            AsyncTaskStatus status = new AsyncTaskStatus();
            status.setStatus(AsyncTaskStatus.STATUS_PENDING);
            status.setProgress(0);
            return status;
        }
        // 在这三个阶段都未找到时可能是因为ID给错了
        return null;
    }

    /********************************************
     * complate<br>
     * 方法业务逻辑详细描述……<br>
     * 任务执行完成后执行的方法
     * @since v1.0.0
     * @param taskId
     * @param taskObject
     * void
     * <br>
     *********************************************/
    public void complate(String taskId, AsyncTaskBase taskObject) {
        if (currentList.containsKey(taskId)) {
            currentList.remove(taskId);
        }
        if (!complateList.containsKey(taskId)) {
            complateList.put(taskId, taskObject);
        }

    }

    /********************************************
     * getRuningCount<br>
     * 方法业务逻辑详细描述……<br>
     * 获取正在执行的任务的数量
     * @since v1.0.0
     * @return
     * int
     * <br>
     *********************************************/
    public int getRuningCount() {
        return currentList.size();
    }

    public int getMaxQueueSize() {
        return maxQueueSize;
    }

    public void setMaxQueueSize(int maxQueueSize) {
        this.maxQueueSize = maxQueueSize;
    }


    public int getDestroyTime() {
        return destroyTime;
    }

    public void setDestroyTime(int destroyTime) {
        this.destroyTime = destroyTime;
    }
}
